package ch.fhnw.qualiscan.application.models;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import ch.fhnw.qualiscan.core.Model;
import ch.fhnw.qualiscan.core.db.pojos.Answer;
import ch.fhnw.qualiscan.core.db.pojos.BestPractice;
import ch.fhnw.qualiscan.core.db.pojos.Domain;
import ch.fhnw.qualiscan.core.db.pojos.DomainDescription;
import ch.fhnw.qualiscan.core.db.pojos.DomainText;
import ch.fhnw.qualiscan.core.db.pojos.Language;
import ch.fhnw.qualiscan.core.db.pojos.Question;
import ch.fhnw.qualiscan.core.db.pojos.Role;
import ch.fhnw.qualiscan.core.db.pojos.Survey;
import ch.fhnw.qualiscan.core.db.pojos.SurveyUserRole;
import ch.fhnw.qualiscan.core.db.pojos.University;
import ch.fhnw.qualiscan.core.db.pojos.User;
/**
 * Model for the API (for flash charts)
 * @author Kevin Mettenberger
 *
 */
public class ApiModel extends Model {
	
	public List<Answer> getAnswersForDomain(Survey survey, Domain domain) {
		@SuppressWarnings("unchecked")
		List<Answer> answerList = hibernateSession.getSession().createQuery("from Answer where survey = :survey and domain = :domain")
		.setParameter("survey", survey)
		.setParameter("domain", domain)
		.list();
		
		return answerList;
		
	}
	
	public List<Answer> getAnswersForDomain(Survey survey, Domain domain, Role role) {
		
		@SuppressWarnings("unchecked")
		List<SurveyUserRole> surList = hibernateSession.getSession().createQuery("from SurveyUserRole where survey = :survey and (role = :role or fillOutRole = :filloutrole)")
		.setParameter("survey", survey)
		.setParameter("role", role)
		.setParameter("filloutrole", role)
		.list();
		
		List<Answer> answerList = new ArrayList<Answer>();
		
		for (int i = 0; i < surList.size(); i++) {
			@SuppressWarnings("unchecked")
			List<Answer> provAnswerList = hibernateSession.getSession().createQuery("from Answer where sur = :sur and domain = :domain")
			.setParameter("sur", surList.get(i))
			.setParameter("domain", domain)
			.list();
			
			
			for (int a = 0; a < provAnswerList.size(); a++) {
				answerList.add(provAnswerList.get(a));
			}
		}  
		
		return answerList;
	}
	
	public List<Answer> getAnswersForQuestion(Survey survey, Question question) {
		@SuppressWarnings("unchecked")
		List<Answer> answerList = hibernateSession.getSession().createQuery("from Answer where survey = :survey and question = :question")
		.setParameter("survey", survey)
		.setParameter("question", question)
		.list();
		
		return answerList;
	}
	
	public List<Answer> getAnswersForQuestion(Survey survey, Question question, Role role) {
		
		
		@SuppressWarnings("unchecked")
		List<SurveyUserRole> surList = hibernateSession.getSession().createQuery("from SurveyUserRole where (role = :role or fillOutRole = :role) and survey = :survey")
		.setParameter("survey", survey)
		.setParameter("role", role)
		.list();
		
		List<Answer> answerList = new ArrayList<Answer>();
		
		for (int i = 0; i < surList.size(); i++) {
			@SuppressWarnings("unchecked")
			List<Answer> provAnswerList = hibernateSession.getSession().createQuery("from Answer where sur = :sur and question = :question")
			.setParameter("sur", surList.get(i))
			.setParameter("question", question)
			.list();
			
			
			for (int a = 0; a < provAnswerList.size(); a++) {
				answerList.add(provAnswerList.get(a));
			}
		}  
		
		return answerList;
	}
	
	public Answer getAnswersForQuestion(SurveyUserRole sur, Question question) {
		Answer answer = (Answer) hibernateSession.getSession().createQuery("from Answer where sur = :sur and question = :question")
		.setParameter("sur", sur)
		.setParameter("question", question)
		.uniqueResult();
		
		return answer;
	}

	public List<Answer> getAnswersForDomain(SurveyUserRole sur, Domain domain) {
		@SuppressWarnings("unchecked")
		List<Answer> answerList = hibernateSession.getSession().createQuery("from Answer where sur = :sur and domain = :domain")
		.setParameter("sur", sur)
		.setParameter("domain", domain)
		.list();
		
		return answerList;
	}
	
	
	public List<BestPractice> getBestPractices(List<Survey> surveyList, List<Domain> domainList, List<User> userList, List<University> universityList, String sort, String sortType, boolean showPrivate, int start, int limit) {
		
		Criteria bestPracticeCriteria = hibernateSession.getSession().createCriteria(BestPractice.class);
		
		//Criterions for survey
		if (surveyList != null) {
			Disjunction surveyDisjungtion = Restrictions.disjunction();
			for (int s = 0; s < surveyList.size(); s++) {
				surveyDisjungtion.add(Restrictions.eq("survey", surveyList.get(s)));
			}
			bestPracticeCriteria.add(surveyDisjungtion);
		}
		
		//Criterions for Domains
		if(domainList != null) {
			Disjunction domainDisjungtion = Restrictions.disjunction();
			for (int d = 0; d < domainList.size(); d++) {
				domainDisjungtion.add(Restrictions.eq("domain", domainList.get(d)));
			}
			bestPracticeCriteria.add(domainDisjungtion);
		}
		
		
		//Criterions for Users
		if(userList != null) {
			Disjunction userDisjungtion = Restrictions.disjunction();
			for (int u = 0; u < userList.size(); u++) {
				userDisjungtion.add(Restrictions.eq("user", userList.get(u)));
			}
			bestPracticeCriteria.add(userDisjungtion);
		}
		
		
		//Criterions for ordering
		if (sort.equals("survey") || sort.equals("domain") || sort.equals("editdate") || sort.equals("user") || sort.equals("title") || sort.equals("bestpractice")) {
			if(sortType.equals("asc")) {
				bestPracticeCriteria.addOrder(Order.asc(sort));
			}
			if(sortType.equals("desc")) {
				bestPracticeCriteria.addOrder(Order.desc(sort));
			}
		}
		
		//Criterion for private
		if (showPrivate == false) {
			bestPracticeCriteria.add(Restrictions.eq("publicpost", 0));
		}
		
		//Criterion limit and offset
		bestPracticeCriteria.setFirstResult(start);
		bestPracticeCriteria.setMaxResults(limit);
		
		bestPracticeCriteria.add(Restrictions.not(Restrictions.eq("bestpractice", "")));
		
		List<BestPractice> bestPracticeList = bestPracticeCriteria.list();
		
		return bestPracticeList;
		
	}
	
	public List<Survey> getSurveyList() {
		List<Survey> surveyList = hibernateSession.getSession().createQuery("from Survey").list();
		
		return surveyList;
	}
	
	public List<Domain> getDomainList() {
		List<Domain> domainList = hibernateSession.getSession().createQuery("from Domain").list();
		
		return domainList;
	}
	
	public DomainText getDomainText(Domain domain, Language language) {
		
		DomainText dt = (DomainText) hibernateSession.getSession().createQuery("from DomainText as dt where dt.domain = :domain and dt.language = :language")
        .setParameter("domain", domain)
        .setParameter("language", language)
        .uniqueResult();
		
		return dt;
	}
	
	public DomainDescription getDomainDescription(Domain domain, Language language) {
		
		DomainDescription dt = (DomainDescription) hibernateSession.getSession().createQuery("from DomainDescription as dt where dt.domain = :domain and dt.language = :language")
        .setParameter("domain", domain)
        .setParameter("language", language)
        .uniqueResult();
		
		return dt;
	}
	

	public BestPractice getBestPractice(int id) {
		BestPractice bestPractice = (BestPractice) hibernateSession.getSession().createQuery("from BestPractice as bp where bp.id = :id")
    	.setParameter("id", id)
    	.uniqueResult();

    	return bestPractice;
	}
	
	public Survey getSurvey(int id) {
		Survey survey = (Survey) hibernateSession.getSession().createQuery("From Survey as survey WHERE survey.id = :id")
		.setParameter("id", id)
		.uniqueResult();
		
		return survey;
	}

	public Domain getDomain(int id) {
		Domain domain = (Domain) hibernateSession.getSession().createQuery("From Domain as domain WHERE domain.id = :id")
		.setParameter("id", id)
		.uniqueResult();
		
		return domain;
	}

	public User getUser(int id) {
		User user = (User) hibernateSession.getSession().createQuery("From User as user WHERE user.id = :id")
		.setParameter("id", id)
		.uniqueResult();
		
		return user;
	}

	public University getUniversity(int id) {
		// TODO Auto-generated method stub
		return null;
	}
}
